const moment = require("moment"); //日期格式化(使用)
const request = require("request");
const UserAgent = require('user-agents');
const crypto = require('crypto');

module.exports = {
  // 队列
  ArrayOutputQueue: function () {
    var arr = [];
    //入队操作  
    this.push = function (element) {
      if (typeof element === "object" && element.length) {
        for (var i = 0; i < element.length; i++) {
          var v = element[i];
          arr.push(v);
        }
      } else {
        arr.push(element);
      }
      return true;
    }
    //出队操作  
    this.pop = function () {
      return arr.shift();
    }
    //指定出队操作  
    this.popByKey = function ({ key = 'key', value = '' }) {
      let item = {};
      arr.map((val, i) => {
        if (val[key] === value) {
          item = val;
          arr.splice(i, 1);
        }
      })
      return item;
    }
    //获取是否存在  
    this.exists = function ({ key = 'key', value = '' }) {
      return arr.find(val => val[key] === value);
    }
    //获取匹配数据  
    this.find = function ({ key = 'key', value = '' }) {
      return arr.filter(val => val[key] === value);
    }
    //获取队首  
    this.getFront = function () {
      return arr[0];
    }
    //获取队尾  
    this.getRear = function () {
      return arr[arr.length - 1]
    }
    //清空队列  
    this.clear = function () {
      arr = [];
    }
    //获取队长  
    this.size = function () {
      return arr.length;
    }
    this.get = function () {
      return arr;
    }
    this.toString = function () {
      return JSON.stringify(arr);
    }
  },
  // redis队列
  RedisTaskQueue: function (name) {
    try {
      const queueName = `Redis_Queue:${name}`;
      //入队操作  
      this.push = function (element) {
        return new Promise((resolve) => {
          global._Redis_.client.HMSET(queueName, element.key, JSON.stringify(element.value), function (err, body) {
            resolve(body)
          })
        });
      }
      //获取队长  
      this.size = function () {
        return new Promise((resolve) => {
          global._Redis_.client.HLEN(queueName, function (err, body) {
            resolve(body || 0);
          });
        });
      }
      //获取是否存在
      this.exists = function (key) {
        return new Promise((resolve) => {
          global._Redis_.client.HEXISTS(queueName, key, function (err, body) {
            resolve(body || 0);
          });
        });
      }
      //获取全部
      this.getAll = function () {
        return new Promise((resolve) => {
          global._Redis_.client.HGETALL(queueName, function (err, body) {
            resolve(body || []);
          });
        });
      }
      // 更新已存在key
      this.update = function (key = null, value = {}) {
        return new Promise(async (resolve) => {
          try {
            let [info] = await this.get(key);
            try {
              info = JSON.parse(info || '{}');
            } catch (error) {
              info = value;
            }
            for (const k in value) {
              if (typeof value[k] === 'object') {
                if (value[k]['EXISTS'] || value[k]['EXISTS'] === 0) {
                  info[k] = info[k] ? info[k] : value[k]['EXISTS'];
                } else {
                  info[k] = value[k];
                }
              } else {
                info[k] = value[k];
              }
            }
            global._Redis_.client.HMSET(queueName, key, JSON.stringify(info), function (err, body) {
              resolve(body || null)
            })
          } catch (error) {
            resolve(null)
          }
        });
      }
      // 获取单个key
      this.get = function (key) {
        return new Promise((resolve) => {
          global._Redis_.client.HMGET(queueName, key, function (err, body) {
            resolve(body || null);
          });
        });
      }
      // 获取单个key
      this.del = function (key) {
        return new Promise((resolve) => {
          global._Redis_.client.HDEL(queueName, key, function (err, body) {
            resolve(body || {});
          });
        });
      }
      //出队(取第一个,并移除)
      this.pop = function () {
        return new Promise((resolve) => {
          try {
            global._Redis_.client.hscan(queueName, 0, 'COUNT', 1, function (err, [cot, res]) {
              const [key, value] = res;
              global._Redis_.client.HDEL(queueName, key);
              try {
                const data = JSON.parse(value);
                resolve(data);
              } catch (error) {
                resolve(value);
              }
            });
          } catch (error) {
            resolve(null)
          }
        });
      }
      //出队(指定,并移除)
      this.popByKey = function (_key) {
        return new Promise((resolve) => {
          global._Redis_.client.hscan(queueName, 0, 'MATCH', _key, 'COUNT', 99999, function (err, [cot, res]) {
            try {
              const [key, value] = res;
              if (!key) throw new Error('获取为空！');
              global._Redis_.client.HDEL(queueName, key);
              try {
                const data = JSON.parse(value);
                resolve(data);
              } catch (error) {
                resolve(value);
              }
            } catch (error) {
              console.log(error);
              resolve(null)
            }
          });
        });
      }
      //清空队列  
      this.clear = async function () {
        return await global._Redis_.client.Hdel(queueName);
      }
    } catch (error) {
      console.error(`RedisQueue Error redis_queue:${name},${this.date()},msg=>${error.message}`);
    }
  },
  /**
   * @description 线程暂停
   * @param {time} time 毫秒数
   * @author zengbao
   */
  sleep: function (time) {
    var promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, time);
    });
    return promise;
  },
  /**
   * @description 获取当前访问用户IP
   * @param {request} req
   * @author 蜂鸟配送
   */
  getClientIp: function (req) {
    return (
      req.headers["x-forwarded-for"] ||
      req.connection.remoteAddress ||
      req.socket.remoteAddress ||
      req.connection.socket.remoteAddress
    );
  },
  /**
   * @description 取随机数
   * @param {number} Min 最小数
   * @param {number} Max 最大数
   * @author 蜂鸟配送
   */
  randomNumBoth: function (Min, Max) {
    let Range = Max - Min;
    let Rand = Math.random();
    let num = Min + Math.round(Rand * Range); //四舍五入
    return num;
  },
  /**
   * @description 格式化日期
   * @param {date||time} mDate 日期
   * @param {string} format 日期格式
   * @author 蜂鸟配送
   */
  date: function (mDate, format) {
    return moment((mDate ? new Date(mDate) : new Date())).format(
      format || "YYYY-MM-DD HH:mm:ss"
    );
  },
  /**
   * @description 发送请求
   * @param {object} opt 提交参数
   * @author 一枚前端
   */
  $ajax: function (opt = {}) {
    return new Promise((resolve, reject) => {
      try {
        if (!opt.url) throw new Error("url , is not null");
        const headers = opt.headers || {};
        let user_agent = new UserAgent({ deviceCategory: 'mobile' });
        delete opt.headers;
        const options = {
          method: 'GET',
          timeout: 10000,
          json: true,
          // proxy: "http://127.0.0.1:8888",
          headers: {
            'Accept-Encoding': 'gzip',
            'Connection': 'keep-alive',
            'User-Agent': user_agent.toString(),
            ...headers
          },
          ...opt
        };
        request(options, (error, response, body) => {
          if (body) {
            resolve(body);
          } else {
            reject(error);
          }
        });
      } catch (error) {
        reject(error);
      }
    })
  },
  //显示内存情况
  memoryUsage: function () {
    let mem = process.memoryUsage();
    let format = function (bytes) {
      return (bytes / 1024 / 1024).toFixed(2) + "MB";
    };
    console.error(
      "Process: heapTotal " +
      format(mem.heapTotal) +
      " heapUsed " +
      format(mem.heapUsed) +
      " rss " +
      format(mem.rss)
    );
  },
  // 函数防抖(一直执行的话只执行最后一次调用)
  debounce: function (fn = () => { }, wait = 300) {
    var timeout = null;
    return function () {
      if (timeout !== null) clearTimeout(timeout);
      timeout = setTimeout(fn, wait);
    }
  },
  // 手机号脱敏
  phoneFilter(phone = '') {
    try {
      return phone.replace(/^(.{3}).*(.{4})$/, '$1****$2')
    } catch (error) {
      return ""
    }
  },
  // 加密
  encrypt(dataStr, { key = 'aes987654231abcdefg', iv = 'abcdefg123456789' } = {}) {
    if (!key || !iv) return "";
    let cipherChunks = [];
    const key_ = crypto.scryptSync(key, 'salt', 32);
    const iv_ = crypto.scryptSync(iv, 'salt', 16);
    let cipher = crypto.createCipheriv('aes-256-cbc', key_, iv_);
    cipher.setAutoPadding(true);
    cipherChunks.push(cipher.update(dataStr, 'utf8', 'base64'));
    cipherChunks.push(cipher.final('base64'));
    return cipherChunks.join('');
  },
  // 解码
  decrypt(dataStr, { key = 'aes987654231abcdefg', iv = 'abcdefg123456789' } = {}) {
    if (!key || !iv) return "";
    const key_ = crypto.scryptSync(key, 'salt', 32);
    const iv_ = crypto.scryptSync(iv, 'salt', 16);
    let cipherChunks = [];
    let decipher = crypto.createDecipheriv('aes-256-cbc', key_, iv_);
    decipher.setAutoPadding(true);
    cipherChunks.push(decipher.update(dataStr, 'base64', 'utf8'));
    cipherChunks.push(decipher.final('utf8'));
    return cipherChunks.join('');
  }
};
